// singletonCallOnce.cpp

#include <iostream>
#include <mutex>

/* 
著名的单例模式需要保证只创建一个对象实例。 
在多线程环境中，这是一项具有挑战性的任务。 
但是，有了std::call_once和std::once_flag这个就很容易做到了。 
现在，以线程安全的方式初始化实例： 
*/

class MySingleton{

  private:
    static std::once_flag initInstanceFlag;
    static MySingleton* instance;
    MySingleton()= default;
    ~MySingleton()= default;

  public:
    MySingleton(const MySingleton&)= delete;
    MySingleton& operator=(const MySingleton&)= delete;

    static MySingleton* getInstance(){
      std::call_once(initInstanceFlag,MySingleton::initSingleton);
      return instance;
    }

    static void initSingleton(){
      instance= new MySingleton();
    }
};

// MySingleton* MySingleton::instance= nullptr;
// std::once_flag MySingleton::initInstanceFlag;


int main(){

  std::cout << std::endl;

  std::cout << "MySingleton::getInstance(): "<< MySingleton::getInstance() << std::endl;
  std::cout << "MySingleton::getInstance(): "<< MySingleton::getInstance() << std::endl;

  std::cout << std::endl;

}

/* 
具有块范围的静态变量
具有块作用域的静态变量将只创建一次。 
这个特征是所谓的Meyers Singleton的基础，以Scott Meyers的名字来命名，这是迄今为止单例模式最优雅的实现:
 */

//一般的单例模式是懒汉单例模式
//建议不要用饿汉单例模式
//Meyers单例模式能够保证在多线程的情况下
//有且只有一个实例，但是不能保证初始化的
//时候操作原子性，初始化数据安全性
//建议使用Meyers单例模式
//如果需要更高要求的单例模式，可以在单例模式中
//使用锁机制

class MySingleton{
public:
  static MySingleton& getInstance(){
    static MySingleton instance;
    return instance;
  }
private:
  MySingleton();
  ~MySingleton();
  MySingleton(const MySingleton&)= delete;
  MySingleton& operator=(const MySingleton&)= delete;

};

MySingleton::MySingleton()= default;
MySingleton::~MySingleton()= default;

int main(){

  MySingleton::getInstance();

}